package com.example.demo.config;

import com.example.demo.domain.entity.Person;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.List;

@Configuration
public class AppRedisConfiguration {


    /**
     * 允许Object类型的key-value，都可以被转为json进行存储。
     * @param redisConnectionFactory 自动配置好了连接工厂
     * @return RedisTemplate<String, Object>
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }

    /**
     * 允许Object类型的key-value，都可以被转为json进行存储。
     * @param redisConnectionFactory 自动配置好了连接工厂
     * @return RedisTemplate<String, T>
     */
    @Bean
    public RedisTemplate<String, Person> personRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Person> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        StringRedisSerializer serializer = new StringRedisSerializer();
        template.setKeySerializer(serializer);
        template.setHashKeySerializer(serializer);
        /*
        GenericJackson2JsonRedisSerializer用于对一般的 Redis 值进行序列化。
        这个序列化器会将 Java 对象（比如Person对象等）序列化为 JSON 格式的字符串存储到 Redis 中，
        这样方便存储和读取各种复杂结构的 Java 对象数据，并且具有较好的通用性。
         */
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        /*
        Jackson2JsonRedisSerializer
        在处理哈希结构中存储Person对象相关数据时，它会将Person对象序列化为 JSON 格式（并且是基于指定的Person类型进行更精准的序列化和反序列化操作），
        保证数据在 Redis 的哈希结构中能正确地存储和后续准确地读取还原为Person对象。
         */
        template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Person.class));
        return template;
    }

    /**
     * 允许Object类型的key-value，都可以被转为json进行存储。
     * @param redisConnectionFactory 自动配置好了连接工厂
     * @return RedisTemplate<String, T>
     */
    @Bean
    public RedisTemplate<String, List<Person>> personListRedisTemplate(RedisConnectionFactory redisConnectionFactory, ObjectMapper objectMapper) {
        RedisTemplate<String, List<Person>> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        StringRedisSerializer serializer = new StringRedisSerializer();
        template.setKeySerializer(serializer);
        template.setHashKeySerializer(serializer);
        CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(List.class, Person.class);
        Jackson2JsonRedisSerializer<List<Person>> hashValueSerializer = new Jackson2JsonRedisSerializer<>(collectionType);
        /*
        Jackson2JsonRedisSerializer
        在处理哈希结构中存储Person对象相关数据时，它会将Person对象序列化为 JSON 格式（并且是基于指定的Person类型进行更精准的序列化和反序列化操作），
        保证数据在 Redis 的哈希结构中能正确地存储和后续准确地读取还原为Person对象。
         */
        template.setValueSerializer(hashValueSerializer);
        template.setHashValueSerializer(hashValueSerializer);
        return template;
    }








}